package com.kingbook.services;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.kingbook.common.utils.DateUtils;
import com.kingbook.common.utils.NumberUtils;
import com.kingbook.common.utils.StringUtils;
import com.kingbook.core.base.SupportService;
import com.kingbook.core.result.JSONPageResult;
import com.kingbook.core.result.JSONResult;
import com.kingbook.entity.Master;
import com.kingbook.entity.Vehicle;
import com.google.common.collect.Maps;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.MapUtils;
import org.checkerframework.checker.units.qual.A;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.PostConstruct;
import java.util.*;

import static com.kingbook.common.enums.DateFormatEnum.DATE;

/**
 * @Author Bucky
 * @Date 2019-12-18 21:37:35
 * @Version 1.0
 */
@Slf4j
@Service
public class WorkorderService extends SupportService {

    @Autowired
    CustomerService customerService;
    @Autowired
    DriverService driverService;
    @Autowired
    VehicleService vehicleService;
    @Autowired
    PartnerService partnerService;
    @Autowired
    WorkspaceService workspaceService;
    @Autowired
    TonsService tonsService;
    @Autowired
    MasterService masterService;

    @PostConstruct
    private void init() {
        setNamespace("Workorder");
    }

    public JSONResult doFavorite(int id, int mid) {
        return update("favorite", putMap(id, mid));
    }

    @Transactional
    public JSONResult updateWorkorder(Map<String, Object> param) {
        int mid = MapUtils.getIntValue(param, "mid");
        int id = MapUtils.getIntValue(param, "id");
        int chargeType = MapUtils.getIntValue(param, "chargeType");
        int useType = MapUtils.getIntValue(param, "useType");
        int allotType = MapUtils.getIntValue(param, "allotType");
        param.put("receipt", chargeType == 2 ? 1 : 0);
        if (useType == 1) {
            int cid = customerService.getCustomerId(mid, MapUtils.getString(param, "customer"), true);
            param.put("wid", workspaceService.getWorkspaceIdByCid(mid, cid, MapUtils.getString(param, "address")));
            param.put("cid", cid);
            param.put("pid", 0);
            param.put("workStatus", 1);
        } else {
            int pid = partnerService.getPartnerId(mid, MapUtils.getString(param, "fromPartner"), true);
            param.put("wid", workspaceService.getWorkspaceIdByPid(mid, pid, MapUtils.getString(param, "address")));
            param.put("cid", 0);
            param.put("pid", pid);
            int workStatus = MapUtils.getIntValue(param, "workStatus");
            if (workStatus != 1)
                param.put("workStatus", chargeType == 1 && partnerService.isSystemPartner(pid, mid) ? 0 : 1);
        }
        if (allotType == 1) {
            param.put("vid", vehicleService.getVehicleId(mid, 0, MapUtils.getString(param, "plateNo")));
            param.put("did", driverService.getDriverId(mid, MapUtils.getString(param, "driver"), true));
            param.put("allotPid", 0);
            int tons = MapUtils.getIntValue(param, "tons");
            int jib = MapUtils.getIntValue(param, "jib");
            tonsService.updateTonsName(mid, tons, jib, 0);
        } else {
            int pid = partnerService.getPartnerId(mid, MapUtils.getString(param, "toPartner"), true);
            param.put("vid", vehicleService.getVehicleId(mid, pid, MapUtils.getString(param, "plateNo")));
            param.put("did", 0);
            param.put("allotPid", pid);
        }
        if (id > 0)
            return modify(param);
        param.put("sn", NumberUtils.uuid10());
        return save(param);
    }

    @Transactional
    public JSONResult confirm(Map<String, Object> param) {
        param.put("workStatus", 1);
        update("cleanConfirm", param);      //先解除原来确认的关系
        update("updateConfirm", param);
        return update("updateConfirmMyOrder", param);
    }

    public JSONResult deny(Map<String, Object> param) {
        param.put("workStatus", 2);
        param.put("fromOid", 0);
        update("cleanConfirm", param);       //先解除原来确认的关系
        return update("updateConfirm", param);
    }

    public JSONResult find(int id, int mid) {
        JSONResult r = find("query", putMap(id, mid));
//        if (r.isSuccess() && r.getCount() > 0) {
//            JSONObject j = r.getData().getJSONObject(0);
//            String date = DateUtils.format(j.getString("workDate"), DATE);
//            String[] d = date.split("-");
//            String[] t = j.getString("workDurationAm").split("-");
//            j.put("workDate", date + " " + t[0] + " " + t[1]);
//            j.put("workDateStr", d[0] + "." + d[1] + "." + d[2] + " " + t[0] + "-" + t[1]);
//            j.put("tons", j.getString("tons"));
//        }
        return r;
    }

    public JSONResult findAllotToPartner(int id, int mid) {
        JSONResult r = find("queryAllotToPartner", putMap(id, mid));
        if (r.isSuccess() && r.getCount() > 0) {
            JSONObject order = r.getData().getJSONObject(0);
            int fromOid = order.getIntValue("fromOid");
            int allotToMid = order.getIntValue("mid");
            order = parseOrder(order, "", true);
            JSONObject allotOrder = new JSONObject();
            if (fromOid > 0) {  //已确认的外派，查询出对应的工单
                JSONResult result = super.find(fromOid, mid);
                if (result.isSuccess() && result.getCount() > 0) {
                    allotOrder = parseOrder(result.getData().getJSONObject(0), "", true);
                }
            }
            JSONArray array = new JSONArray();
            order.put("fromOid", fromOid);
            order.put("mid", allotToMid);
            array.add(order);
            array.add(allotOrder);
            r.setData(array);
        }
        return r;
    }

    public JSONResult queryAllot(Map<String, Object> param) {
        JSONResult result = query("queryAllot", param);
        JSONArray array = new JSONArray();
        JSONArray orderArr = result.getData();
        for (int i = 0; i < orderArr.size(); i++) {
            JSONObject order = orderArr.getJSONObject(i);
            array.add(parseOrder(order, "", true));
        }
        result.setData(array);
        return result;
    }

    public JSONPageResult queryForPages(Map<String, ?> param) {
        boolean isWorkOrder = MapUtils.getBoolean(param, "isWorkOrder", true);
        JSONPageResult orders = queryForPages(isWorkOrder ? "query" : "queryAllotToPartner", isWorkOrder ? "getRows" : "getAllotToPartnerRows", param);
        JSONArray array = new JSONArray();
        JSONArray orderArr = orders.getData();
        Master master = masterService.getById(MapUtils.getIntValue(param, "mid"));
        String today = DateUtils.format(DateUtils.now(), DATE);
        JSONObject json;
        for (int i = 0; i < orderArr.size(); i++) {
            JSONObject order = orderArr.getJSONObject(i);
            String date = order.getString("workDate");
            if (today.equals(date)) {
                date = "今日";
            } else {
                String[] d = date.split("-");
                date = d[1] + "/" + d[2];
            }
            json = parseOrder(order, date, isWorkOrder);
            if (!master.isShowAmount())
                json.put("amount", "****");
            array.add(json);
        }
        orders.setData(array);
        return orders;
    }

    public boolean hasPartnerOrder(int pid, int mid) {
        Map<String, Object> param = Maps.newHashMap();
        param.put("mid", mid);
        param.put("pid", pid);
        JSONResult result = query("hasPartnerOrder", param);
        return result.isSuccess() && Integer.parseInt(result.getDataElement("count")) > 0;
    }

    public JSONResult query(Map<String, ?> param) {
        JSONResult result = query("query", param);
        JSONArray array = new JSONArray();
        JSONArray orderArr = result.getData();
        JSONObject meta = new JSONObject();
        int totalAmount = 0, len = orderArr.size();
        float chargeNums = 0;
        String owner = "", startDate = "", endDate = "";
        for (int i = 0; i < len; i++) {
            JSONObject order = orderArr.getJSONObject(i);
            JSONObject json = new JSONObject();
            json.put("seq", i + 1);
            json.put("workDate", order.getString("workDate"));
            json.put("plateNo", order.getString("plateNo"));
            json.put("tons", getTonsAndJibs(order));
            json.put("amount", order.getIntValue("amount") + "元");
            json.put("duration", order.getIntValue("duration") == 0 ? "" : order.getIntValue("duration") + "小时");
            json.put("chargeNum", order.getFloatValue("chargeNum") == 0 ? "" : order.getString("chargeNum").replace(".0", "") + "个班");
            int useType = order.getInteger("useType");
            json.put("owner", useType == 1 ? order.getString("customer") : order.getString("fromPartner"));
            json.put("address", order.getString("address"));
//            json.put("toPartner", order.getString("toPartner"));
            json.put("task", order.getString("toPartner") + " " + order.getString("task"));
            array.add(json);
            totalAmount += order.getIntValue("amount");
            chargeNums += order.getFloatValue("chargeNum");
            if (StringUtils.isEmpty(owner))
                owner = json.getString("owner");
            if (i == 0)
                endDate = order.getString("workDate");
            if (i == len - 1)
                startDate = order.getString("workDate");
        }
        meta.put("owner", owner+"台账明细表");
        meta.put("nums", "数量: " + len + "个");
        meta.put("chargeNums", ("台班: " + chargeNums + "个").replace(".0", ""));
        meta.put("totalAmount", "总额: " + totalAmount + "元");
        meta.put("startDate", "开始时间: " + startDate);
        meta.put("endDate", "结束时间: " + endDate);
        meta.put("createTime", DateUtils.getDateTime());
        result.setData(array);
        result.setMsg(meta.toJSONString());
        return result;
    }

    public JSONResult queryForReceipt(Map<String, Object> param) {
        JSONResult result = query("queryForReceipt", param);
        JSONArray arr = result.getData();
        JSONArray array = new JSONArray();
        for (int i = 0; i < arr.size(); i++) {
            JSONObject order = arr.getJSONObject(i);
            int financeId = order.getIntValue("receiptId");
            JSONObject json = parseOrder(order, "", true);
            json.put("financeId", financeId);
            array.add(json);
        }
        result.setData(array);
        return result;
    }

    public JSONResult queryForPay(Map<String, Object> param) {
        JSONResult result = query("queryForPay", param);
        JSONArray arr = result.getData();
        JSONArray array = new JSONArray();
        for (int i = 0; i < arr.size(); i++) {
            JSONObject order = arr.getJSONObject(i);
            int financeId = order.getIntValue("payId");
            JSONObject json = parseOrder(order, "", true);
            json.put("financeId", financeId);
            array.add(json);
        }
        result.setData(array);
        return result;
    }

    private JSONObject parseOrder(JSONObject order, String date, boolean isWorkOrder) {
        JSONObject json = new JSONObject();
        json.put("id", order.getIntValue("id"));
        json.put("mid", order.getIntValue("mid"));
        json.put("favorite", order.getBooleanValue("favorite"));
        json.put("workDate", date.length() > 0 ? date : order.getString("workDate"));
        json.put("receiptColor", order.getIntValue("chargeType") == 2 || order.getIntValue("receiptId") > 0 ? "green" : "red");  // 1-已付款 2-未付款
        json.put("amount", order.getIntValue("amount"));
        json.put("duration", order.getIntValue("duration") == 0 ? "" : order.getIntValue("duration") + "小时");
        json.put("chargeNum", order.getFloatValue("chargeNum") == 0 ? "" : order.getString("chargeNum").replace(".0", "") + "个班");
        json.put("icon", order.getIntValue("chargeType") == 1 ? "arrearage" : "cash");     // 显示不同icon 1-order 2-money
        json.put("image", order.getString("image"));
        if (order.getIntValue("allotType") == 1) {
            json.put("title", order.getString("plateNo") + "  " + getTonsAndJibs(order));
            json.put("driver", "【驾驶员】" + order.getString("driver"));
        } else {
            json.put("title", order.getString("plateNo") + "  " + getTonsAndJibs(order) + "【外派】");
            json.put("subTitle", "【外派】" + order.getString("toPartner"));
        }
        int useType = order.getInteger("useType");
        json.put("useType", useType);
        json.put("owner", useType == 1 ? order.getString("customer") : order.getString("fromPartner"));
        json.put("fromOid", order.getString("fromOid"));
        json.put("toOid", order.getString("toOid"));
        json.put("fromPartner", order.getString("fromPartner"));
        json.put("partner", order.getString("partner"));
        json.put("toPartner", order.getString("toPartner"));
        json.put("address", order.getString("address"));
        json.put("task", StringUtils.isNotEmpty(order.getString("task")) ? order.getString("task") : '无');
        json.put("workStatus", order.getString("workStatus"));
        json.put("receiptId", order.getString("receiptId"));
        json.put("payId", order.getString("payId"));
        return json;
    }

    private String getTonsAndJibs(JSONObject order) {
        Integer jib = order.getInteger("jib");
        return order.getString("tons") + "T" + (jib != null && jib > 0 ? "-" + jib : "");
    }

    public JSONResult statistics(Map<String, Object> param) {
        JSONResult r = query("statistics", param);
        JSONArray array = r.getData();
        JSONObject json = new JSONObject();
        for (int i = 0; i < array.size(); i++) {
            JSONObject js = array.getJSONObject(i);
            json.put(js.getString("type"), js.getIntValue("count"));
        }
        return JSONResult.success(json);
    }

    public JSONResult statisticsForUse(int mid) {
        Map<String, Object> param = new HashMap<>(1);
        param.put("mid", mid);
        JSONResult re = query("statisticsForUse", param);
        int f = 0, c = 0, d = 1;
        if (re.isSuccess() && re.getCount() > 0) {
            JSONObject json = re.getData().getJSONObject(0);
            c = json.getIntValue("count");
            f = json.getIntValue("favorite");
            Date date = json.getDate("createTime");
            if (date != null) {
                Calendar cl = Calendar.getInstance();
                cl.setTime(date);
                d = DateUtils.getDaysBetween(cl, Calendar.getInstance()) + 1;
            }
        }
        JSONObject json = new JSONObject();
        json.put("favoriteNum", f);
        json.put("countNum", c);
        json.put("days", d);
        return JSONResult.success(json);
    }


    public JSONResult ratioCustomerReceipt(Map<String, ?> param) {
        return ratioRepo(query("ratioCustomerReceipt", param));
    }

    public JSONResult ratioPartnerReceipt(Map<String, ?> param) {
        return ratioRepo(query("ratioPartnerReceipt", param));
    }

    public JSONResult ratioPartnerPay(Map<String, ?> param) {
        return ratioRepo(query("ratioPartnerPay", param));
    }

    private JSONResult ratioRepo(JSONResult jr) {
        int total = 0, cash = 0, receipt = 0, payedTotal = 0, payedCash = 0, payed = 0;
        JSONArray ja = jr.getData();
        JSONArray series = new JSONArray();
        JSONObject jo;
        for (int i = 0; i < ja.size(); i++) {
            jo = ja.getJSONObject(i);
            total += jo.getIntValue("total");
            cash += jo.getIntValue("cash");
            receipt += jo.getIntValue("receipt");
            jo.put("unReceipt", jo.getIntValue("total") - jo.getIntValue("cash") - jo.getIntValue("receipt"));
            payedTotal += jo.getIntValue("payedTotal");
            payedCash += jo.getIntValue("payedCash");
            payed += jo.getIntValue("payed");
            jo.put("unPayed", jo.getIntValue("payedTotal") - jo.getIntValue("payedCash") - jo.getIntValue("payed"));
            series.add(jo);
        }
        JSONObject json = new JSONObject();
        json.put("total", total);
        json.put("cash", cash);
        json.put("receipt", receipt);
        json.put("unReceipt", total - cash - receipt);
        json.put("payedTotal", payedTotal);
        json.put("payedCash", payedCash);
        json.put("payed", payed);
        json.put("unPayed", payedTotal - payedCash - payed);
        json.put("series", series);
        return JSONResult.success(json);
    }

    public String getStartDate(Map<String, Object> param) {
        JSONResult result = query("getStartDate", param);
        if (result.isSuccess() && result.getCount() > 0) {
            return result.getDataElement("startDate");
        }
        return DateUtils.getDate();
    }

    public String getAllotStartDate(Map<String, Object> param) {
        JSONResult result = query("getAllotStartDate", param);
        if (result.isSuccess() && result.getCount() > 0) {
            return result.getDataElement("startDate");
        }
        return DateUtils.getDate();
    }

    public Map<String, Object>[] getDistinctTons(Map<String, Object> param) {
        return queryMap("getDistinctTons", param);
    }

    public Map<String, Object>[] getDistinctWorkspace(Map<String, Object> param) {
        return queryMap("getDistinctWorkspace", param);
    }

    public Map<String, Object>[] getDistinctCustomer(Map<String, Object> param) {
        return queryMap("getDistinctCustomer", param);
    }

    public Map<String, Object>[] getDistinctPartner(Map<String, Object> param) {
        return queryMap("getDistinctPartner", param);
    }

    public Map<String, Object>[] getDistinctAllotPartner(Map<String, Object> param) {
        return queryMap("getDistinctAllotPartner", param);
    }

    public JSONResult updateToReceipt(int financeId, int type, int mid, List ids) {
        Map<String, Object> param = Maps.newHashMap();
        param.put("mid", mid);
        param.put("financeId", financeId);
        param.put("ids", ids);
        return update(type == 1 ? "updateToReceipt" : "updateToPay", param);
    }

    public JSONResult updateToUnReceipt(int financeId, int type, int mid) {
        Map<String, Object> param = Maps.newHashMap();
        param.put("mid", mid);
        param.put("financeId", financeId);
        return update(type == 1 ? "updateToUnReceipt" : "updateToUnPay", param);
    }

    public int getRows(int id, int mid) {
        Map<String, Object> param = Maps.newHashMap();
        param.put("id", id);
        param.put("mid", mid);
        return getRows("getRows", param);
    }
}
